import {pushTarget,popTarget} from "./dep";

/**
 * 1. 渲染组件会用到
 * 2. 计算属性会用到
 * 3. vm.watch会用到
 * */
let id = 0; // 每个watcher都有一个唯一的标识
class Watcher {
    /**
     *
     * @param vm 当前组件的实例 new Vue
     * @param exprOrFn 用户可能传入的是一个表达式 也有可能传入的是一个函数
     * @param cb 用户传入的回调函数 vm.$watch('msg',cb)
     * @param opts 一些其他参数
     */
    constructor(vm,exprOrFn,cb=()=>{},opts={}) {
        this.vm = vm;
        this.exprOrFn = exprOrFn;
        if (typeof exprOrFn === 'function') {
            this.getter = exprOrFn; // 让getter等于new Watcher传入的第二个参数
        }
        this.cb = cb;
        this.deps = [];
        this.depsId = new Set();
        this.opts = opts;
        this.id = id++;

        this.get(); // 让getter执行
    }

    // 默认创建watcher就会调用它↓
    // 给数据赋值导致视图更新会调它↓
    get()/*←取这名 杂想的???*/{
        pushTarget(this); // 当前的watcher,即 new Watcher时的那个实例。 数据变化了,需要让watcher重新执行

        // ↓这个getter即是new Watcher时传的第二个参数【updateComponent】(vue库的index.js中)
        this.getter/*←emmm 之所以叫getter...??不知道这个人咋想的,可能是因为暗示会在observer.js里Object.define的getter里会做手脚*/();

        popTarget();
    }

    addDep(dep) { // 同一个watcher 不应该重复记录dep
        let id = dep.id; //msg 的
        if(!this.depsId.has(id)) { // ←起到了去重的作用
            this.depsId.add(id);
            this.deps.push(dep); // 这样就让watcher 记住了当前的dep
            dep.addSub(this);
        }
    }

    update(){
        this.get()
    }
}

export default Watcher;